{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "toc": true
   },
   "source": [
    "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n",
    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Stochastic-modelling-and-derivatives-in-traditional-markets-and-in-crypto-markets---TD-2\" data-toc-modified-id=\"Stochastic-modelling-and-derivatives-in-traditional-markets-and-in-crypto-markets---TD-2-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Stochastic modelling and derivatives in traditional markets and in crypto-markets - TD 2</a></span><ul class=\"toc-item\"><li><ul class=\"toc-item\"><li><span><a href=\"#Exercice-0:-échauffement-avec-Python\" data-toc-modified-id=\"Exercice-0:-échauffement-avec-Python-1.0.1\"><span class=\"toc-item-num\">1.0.1&nbsp;&nbsp;</span>Exercice 0: échauffement avec Python</a></span></li></ul></li><li><span><a href=\"#Exercice-1:-Pricing-d'options-européennes-dans-le-modèle-binomial\" data-toc-modified-id=\"Exercice-1:-Pricing-d'options-européennes-dans-le-modèle-binomial-1.1\"><span class=\"toc-item-num\">1.1&nbsp;&nbsp;</span>Exercice 1: Pricing d'options européennes dans le modèle binomial</a></span><ul class=\"toc-item\"><li><ul class=\"toc-item\"><li><span><a href=\"#$\\blacktriangleright$-Portefeuille-de-couverture\" data-toc-modified-id=\"$\\blacktriangleright$-Portefeuille-de-couverture-1.1.0.1\"><span class=\"toc-item-num\">1.1.0.1&nbsp;&nbsp;</span>$\\blacktriangleright$ Portefeuille de couverture</a></span></li></ul></li><li><span><a href=\"#Question-1:-calcul-du-prix-par-récursion.-Compléter-les-cellules-ci-dessous.\" data-toc-modified-id=\"Question-1:-calcul-du-prix-par-récursion.-Compléter-les-cellules-ci-dessous.-1.1.1\"><span class=\"toc-item-num\">1.1.1&nbsp;&nbsp;</span>Question 1: calcul du prix par récursion. Compléter les cellules ci-dessous.</a></span></li><li><span><a href=\"#Cas-à-$n$-dates\" data-toc-modified-id=\"Cas-à-$n$-dates-1.1.2\"><span class=\"toc-item-num\">1.1.2&nbsp;&nbsp;</span>Cas à $n$ dates</a></span></li><li><span><a href=\"#Questions-1.1,-1.2-et-1.3:-une-vérification-et-un-peu-d'affichage\" data-toc-modified-id=\"Questions-1.1,-1.2-et-1.3:-une-vérification-et-un-peu-d'affichage-1.1.3\"><span class=\"toc-item-num\">1.1.3&nbsp;&nbsp;</span>Questions 1.1, 1.2 et 1.3: une vérification et un peu d'affichage</a></span></li><li><span><a href=\"#Question-2:-calcul-du-delta\" data-toc-modified-id=\"Question-2:-calcul-du-delta-1.1.4\"><span class=\"toc-item-num\">1.1.4&nbsp;&nbsp;</span>Question 2: calcul du delta</a></span></li></ul></li></ul></li></ul></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Stochastic modelling and derivatives in traditional markets and in crypto-markets - TD 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 0: échauffement avec Python\n",
    "\n",
    "On évalue et on affiche la fonction\n",
    "\n",
    "$$\n",
    "f(x) = x^2 \\sin(x)\n",
    "$$\n",
    "\n",
    "sur l'intervalle $[-\\pi, \\pi]$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Un array (vecteur) contenant une grille\n",
    "## régulière sur l'intervalle [- 2, 2]\n",
    "x = np.linspace(-np.pi, np.pi, 100)\n",
    "\n",
    "################################################\n",
    "## TO DO: créer un array y contenant les\n",
    "## valeurs de la fonction f sur la grille x\n",
    "################################################\n",
    "y = ????\n",
    "\n",
    "## Affichage\n",
    "plt.plot( ???? , ???? , color=\"blue\", label=r\"$f(x) = x^2 \\sin(x)$\")\n",
    "\n",
    "plt.legend(loc=\"best\", fontsize=14)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercice 1: Pricing d'options européennes dans le modèle binomial\n",
    "\n",
    "On s'intéresse au calcul du prix d'un payoff Européen $\\Psi(S_{t_n})$ dans le modèle binomial avec paramètres $ u> d$, valeur initial de l'actif $S_0$, et en présence d'un taux d'intéret $r$ sur chaque période: $1$ Euro en $t_i$ devient $1+r$ Euros en $t_{i+1}$.\n",
    "\n",
    "#### $\\blacktriangleright$ Portefeuille de couverture\n",
    "\n",
    "Comme démontré dans le cours, en supposant un modèle binomial, pour chaque payoff $\\Psi(S_{t_n})$ il existe un unique portefeuille autofinançant $(V_{t_i})_{i=0,\\dots,n}$ qui réplique exactement le payoff à maturité. \n",
    "\n",
    "Ce portefeuille s'écrit à chaque date $t_i$ comme une fonction $v(t_i, S_{t_i})$ de la valeur courante du sous-jacent en $t_i$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 1: calcul du prix par récursion. Compléter les cellules ci-dessous.\n",
    "\n",
    "Tout d'abord, nous définissons une fonction Python qui renvoie la fonction valeur du portefeuille de couverture $v(t_i, \\cdot)$ à la date $t_i$ (en d'autres termes: la fonction de prix de l'option) à partir de la connaissance de la fonction $v(t_{i+1}, \\cdot)$ à la date $t_{i+1}$.\n",
    "\n",
    "Dans la cellule ci-dessous, la fonction $v(t_{i+1}, \\cdot)$ à la date $t_{i+1}$ est représentée par la variable Python `fonction_prix_t_i_plus_one`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def prix_recursion(r, u, d, fonction_prix_t_i_plus_one):\n",
    "    \"\"\"\n",
    "    On effectue une itération de la date t_{i+1} à la date t_i.\n",
    "    \n",
    "    Paramètres\n",
    "    + r, u, d: les paramètres du modèle binomial \n",
    "    + fonction_prix_t_i_plus_one (une fonction Python):\n",
    "        La fonction de prix v(t_{i+1}, .) à la date t_{i+1}.\n",
    "        Doit prendre comme argument la valeur S_{t_{i+1}} du sous-jacent à la date t_{i+1}.\n",
    "    \n",
    "    Output: Une fonction Python, la fonction de prix v(t_i, .) à la date t_i.\n",
    "            Doit prendre comme argument la valeur S_{t_i} du sous-jacent.\n",
    "    \"\"\"\n",
    "    ####################################################\n",
    "    ## TO DO: calculer les coefficients q_up et q_down\n",
    "    ####################################################\n",
    "    q_up = ????\n",
    "    q_down = ????\n",
    "    \n",
    "    ####################################################\n",
    "    ## TO DO: compléter avec le calcul de la fonction de\n",
    "    ## prix à la date t_i   \n",
    "    ####################################################\n",
    "    def fonction_prix_t_i(S_i):\n",
    "        valeur = ????\n",
    "        return valeur\n",
    "    \n",
    "    return fonction_prix_t_i"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nous pouvons déjà tester, pour le problème à $n=1$ période, le pricing d'un call $\\Psi(S) = (S-K)^+$ (considéré dans le cours, cf. slide 6)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "S_0 = 4\n",
    "u = 2\n",
    "d = 1/2\n",
    "r = 1/4\n",
    "K = 5\n",
    "\n",
    "## On verifie la condition d'absence d'arbitrage sur le marché contenant S et le taux r:\n",
    "assert(d < 1 + r < u)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calculer le prix en $t_0 = 0$ de l'option $\\Psi(S_{t_1})$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def payoff_call(S, strike = K):\n",
    "    return np.maximum(S - strike, 0)\n",
    "\n",
    "fonction_prix = ????\n",
    "\n",
    "prix = ????\n",
    "\n",
    "print(\"Prix en t_0 du call de payoff (S_{t_1} - %1.1f)^+: %1.2f\" %(K,prix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cas à $n$ dates"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dans le cas $n$ dates $t_1, \\dots, t_n$, on peut procéder de manière rétrograde pour calculer le prix en $t_0$ (et à toute date $t_i \\le t_n$, en fait) d'un payoff $\\Psi(S_{t_n})$.\n",
    "\n",
    "On pourra faire appel à la fonction `prix_recursion` définie plus haut, en appliquant le nombre approprié d'itérations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def prix_t_i(r, u, d, payoff, i, n):\n",
    "    \"\"\"\n",
    "    Prix à la date t_i, i < n, de l'option de maturité t_n et de payoff = payoff(S_{t_n})\n",
    "        \n",
    "    Output: Une fonction Python, la fonction de prix v(t_i, .) à la date t_i.\n",
    "            Prendra comme argument la valeur S_{t_i} du sous-jacent.\n",
    "    \"\"\"\n",
    "    fonction_prix = payoff\n",
    "    \n",
    "    ## Attention à l'iteration sur l'objet \"range\":\n",
    "    ## range(n, i, -1) contient les entiers ordonnés de n à i+1 (c'est ce que l'on veut ci-dessous)\n",
    "    \n",
    "    for j in range(n, i, -1):\n",
    "        ####################################################\n",
    "        ## TO DO: compléter avec le calcul de la fonction de\n",
    "        ## prix à la date t_i \n",
    "        ####################################################        \n",
    "        fonction_prix = ????\n",
    "    \n",
    "    return fonction_prix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Toujours pour le payoff  $\\Psi(S) = (S-K)^+$ défini plus haut, on peut maintenant calculer le prix à n'importe quelle date $t_i$ pour une maturité $t_n > t_i$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Maturité t_n = n\n",
    "n = 5\n",
    "\n",
    "## Date courante t_i = i\n",
    "i = 2\n",
    "\n",
    "S_ti = 100\n",
    "K = 120\n",
    "u = 1.2; d = 0.8; r = 0.02\n",
    "\n",
    "def payoff_call(S, strike = K):\n",
    "    return np.maximum(S - strike, 0)\n",
    "\n",
    "assert(d < 1 + r < u)\n",
    "\n",
    "#######################################\n",
    "## TO DO: créer la fonction de prix de \n",
    "## l'option à la date t_i\n",
    "#######################################\n",
    "fonction_prix = ????\n",
    "\n",
    "prix = ????\n",
    "\n",
    "print(\"Prix en t_%1.0f du call de payoff (S_{t_%1.0f} - %1.1f)^+ lorsque S_ti = %1.2f: %1.2f\" %(i, n, K, S_ti, prix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Questions 1.1, 1.2 et 1.3: une vérification et un peu d'affichage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\blacktriangleright$ __1.1 Vérifier__ que le prix comptant du payoff $S_{t_n}$ dans le modèle binomial est bien égal à $S_0$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#######################################\n",
    "## TO DO: vérifier que l'on a bien\n",
    "## prix comptant(S_t_n) = S_0\n",
    "#######################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\blacktriangleright$ __1.2 Compléter__ les cellules ci-dessous, qui affichent\n",
    "  - La fonction de prix $v(t_0, S_0)$ d'un call $(S_{t_n} - K)^+$ de strike donné en fonction de la valeur du sous-jacent $S_0$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Une grille de 50 valeurs possibles du sous-jacent S_0 entre K/4 et 2*K\n",
    "K = 120\n",
    "nb_points = 50\n",
    "spots = np.linspace(K/4, 2*K, nb_points)\n",
    "\n",
    "call_prices = np.zeros(nb_points)\n",
    "\n",
    "n = 10\n",
    "i = 0\n",
    "\n",
    "########################################################\n",
    "## TO DO: compléter avec le calcul du prix à la date\n",
    "## t_0 du payoff (S_{t_n} - K)^+, pour les différentes\n",
    "## valeurs du spot S_0\n",
    "########################################################\n",
    "\n",
    "fonction_prix = ????\n",
    "\n",
    "for j in range(nb_points):\n",
    "    call_prices[j] = ???"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nous pouvons maintenant afficher les prix calculés en fonction de la valeur du spot $S_0$, ainsi que la borne inférieure pour un prix de call (valide dans n'importe quel modèle, voir cours 1):\n",
    "\n",
    "$$\n",
    "C( (S_{t_n} - K)^+, t_n) \\ge C( S_{t_n} - K, t_n) = S_{t_0} - K \\, B(t_0, t_n)\n",
    "= S_{t_0} - \\frac{K}{(1+r)^{t_n}}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "########################################################\n",
    "## TO DO: compléter les appels de la fonction plt.plot\n",
    "## avec les variables spot et prix\n",
    "########################################################\n",
    "\n",
    "plt.plot( ???? , ???? , color=\"b\", label=\"Call price\")\n",
    "\n",
    "########################################################\n",
    "## TO DO: calculer et afficher la borne inf pour le prix\n",
    "## du call\n",
    "########################################################\n",
    "\n",
    "borne_inf = ????\n",
    "\n",
    "plt.plot( ???? , ???? , color=\"k\", label=u\"Borne inf $(S - K/(1+r)^n)^+$\")\n",
    "\n",
    "plt.xlabel(\"spot S\", fontsize=12)\n",
    "plt.ylabel(\"price\", fontsize=12)\n",
    "\n",
    "plt.legend(loc=\"best\", fontsize=12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\blacktriangleright$ __1.3 Compléter__ les cellules ci-dessous, qui calculent et affichent\n",
    "  - Le prix en $t=0$ d'un call $(S_{t_n} - K)^+$ de spot $S_0$ donné en fonction de la valeur du prix d'exercice $K$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Une grille de 50 strikes entre S_0/3 et 3*S_0\n",
    "S_0 = 100\n",
    "\n",
    "nb_points = 50\n",
    "strikes = np.linspace(S_0/3, 3*S_0, nb_points)\n",
    "\n",
    "call_prices = np.zeros(nb_points)\n",
    "\n",
    "n = 10\n",
    "i = 0\n",
    "\n",
    "########################################################\n",
    "## TO DO: compléter avec le calcul des prix à la date\n",
    "## t_0 des payoffs (S_{t_n} - K)^+, pour les différentes\n",
    "## valeurs du strike K.\n",
    "########################################################\n",
    "\n",
    "for j in range(nb_points):\n",
    "    K = strikes[j]\n",
    "    \n",
    "    ## Attention: il faut redefinir un nouveau payoff \n",
    "    ## pour chaque valeur de K\n",
    "    \n",
    "    def payoff_call(S):\n",
    "        return ????\n",
    "\n",
    "    fonction_prix = ????\n",
    "\n",
    "    call_prices[j] = ????"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "########################################################\n",
    "## TO DO: compléter les appels de la fonction plt.plot\n",
    "## avec les variables strike et prix\n",
    "########################################################\n",
    "\n",
    "plt.plot( ???? , ???? , color=\"b\", label=\"Call price\")\n",
    "\n",
    "## On affiche la borne inf en fonction des strikes\n",
    "borne_inf = ????\n",
    "\n",
    "plt.plot( ????, ????, color=\"k\", label=u\"Borne inf $(S_0 - K/(1+r)^n)^+$\")\n",
    "\n",
    "plt.xlabel(\"strike K\", fontsize=12)\n",
    "plt.ylabel(\"price\", fontsize=12)\n",
    "\n",
    "plt.legend(loc=\"best\", fontsize=12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 2: calcul du delta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\blacktriangleright$ __Compléter__ avec le calcul du delta de l'option $\\delta(t_i,S_{t_i})$ à chaque date $t_i$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": false,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": true,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
